package ch.coredump.tagcloud.scene;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.logging.Logger;

import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.Shape;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import ch.coredump.tagcloud.CloudConsts;
import ch.coredump.tagcloud.CloudSettings;
import ch.coredump.tagcloud.data.CloudWord;
import ch.coredump.tagcloud.util.CloudUtil;

public class CloudCreator {
	private Logger log = Logger.getLogger(CloudCreator.class.toString());

	public Group createCloud(Group root, List<CloudWord> words,
			DisplayType displayTyp) {

		switch (displayTyp) {
		case RANDOM:
			return createCloudRandom(root, words);
		case ALPHA:
			return createCloudAlpha(root, words);
		case WEIGHT:
			return createCloudCount(root, words);
		default:
			break;
		}
		return null;
	}

	/**
	 * creates a tag cloud ordered by word count.
	 * 
	 * @param root
	 *            root to attach the tags to
	 * @param words
	 *            list of words
	 */
	private Group createCloudCount(Group root, List<CloudWord> words) {
		// sort with count comparator
		Collections.sort(words);

		attachCloudWords(root, words);

		return root;
	}

	/**
	 * attaches the CloudWords to the given root.
	 * 
	 * @param root
	 *            group to attach the words to
	 * @param words
	 *            Ordered List of words
	 */
	private void attachCloudWords(Group root, List<CloudWord> words) {
		int x = 0;
		int y = 150;
		int hSpace = 15;
		int vSpace = 15;

		Iterator<CloudWord> iterator = words.iterator();
		while (iterator.hasNext()) {
			CloudWord word = iterator.next();
			Shape tag = createTag(word, x, y);
			x += tag.getBoundsInLocal().getWidth() + hSpace;
			if (x + hSpace >= CloudConsts.SCREEN_X) {
				// overflow set this tag to the x = 0
				x = 0;
				y += tag.getBoundsInLocal().getHeight() + vSpace;
				tag = createTag(word, x, y);
				x += tag.getBoundsInLocal().getWidth() + hSpace;
			}
			root.getChildren().add(tag);
		}
	}

	private Group createCloudAlpha(Group root, List<CloudWord> words) {
		// sort with count comparator
		Collections.sort(words, new AlphabeticComparator());
		attachCloudWords(root, words);
		return root;
	}

	private Group createCloudRandom(Group root, List<CloudWord> words) {
		Random r = new Random(System.currentTimeMillis());

		for (CloudWord word : words) {

			int x = r.nextInt(CloudConsts.SCREEN_X - 100);
			int y = r.nextInt(CloudConsts.SCREEN_Y - 100);

			Shape tag = createTag(word, x, y);
			root.getChildren().add(tag);
		}
		return root;
	}

	/**
	 * creates a Tag
	 * 
	 * @param x
	 *            x position
	 * @param y
	 *            y position
	 * @return the newly created tag
	 */
	private Shape createTag(CloudWord word, int x, int y) {
		CloudSettings settings = CloudSettings.instance();

		// set font size depending on the words 'weight'
		double fontSize = CloudUtil.getValue(settings.getMinFontSize(),
				settings.getMaxFontSize(), word.getWeigth());

		Text t = new Text(x, y, word.getWord());

		t.setFill(Color.BLACK);

		Font font = new Font("Arial", fontSize);

		t.setFont(font);

		// GaussianBlur b = new GaussianBlur();
		// b.setRadius(3);
		// t.setEffect(b);

		log.finer("created tag at:" + x + " y:" + y);

		return t;
	}
}
